package org.obm.mina;

import java.io.IOException;
import java.nio.ByteBuffer;

import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MinaIoSessionOutputStream extends MinaOutputStream {
	private final IoSession session;
	private WriteFuture lastFuture;
	@SuppressWarnings("unused")
	private static final Logger logger = LoggerFactory
			.getLogger(MinaIoSessionOutputStream.class);

	/**
	 * Creates a new output stream for writing output bytes using a specified
	 * buffer size.
	 * 
	 * @param session
	 *            the IoSession to which bytes are written
	 * @param size
	 *            the size of the output buffer
	 */
	public MinaIoSessionOutputStream(IoSession session, int size) {
		super(size);
		this.session = session;
	}

	/**
	 * Creates a new output stream for writing output bytes with a default
	 * buffer size of 8192 bytes.
	 * 
	 * @param session
	 *            the IoSession to which bytes are written
	 */
	public MinaIoSessionOutputStream(IoSession session) {
		this(session, 8192);
	}

	@Override
	protected void flushBytes(ByteBuffer bb) throws IOException {
		lastFuture = session.write(MinaUtil.toMinaByteBuffer(bb));
	}

	@Override
	public boolean join(long timeout) {
		if (timeout < 0) {
			throw new IllegalArgumentException("Invalid timeout");
		}
		return join(lastFuture, timeout);
	}

	private boolean join(WriteFuture future, long timeout) {
		if (future == null) {
			return true;
		}
		if (timeout > 0) {
			future.awaitUninterruptibly(timeout);
		} else {
			future.awaitUninterruptibly();
		}
		return future.isWritten();
	}

	public void flushAndClose() {
		IoFutureListener<IoFuture> listener = new IoFutureListener<IoFuture>() {

			@Override
			public void operationComplete(IoFuture future) {
				future.getSession().close(true);
			}
		};
		lastFuture.addListener(listener);
	}

}
